package com.interviews.atomic;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * AtomicInteger 在高并发下性能不好，如何解决？以及为什么会出现这种情况？
 *
 * 对于 AtomicLong 内部的 value 属性而言，也就是保存当前 AtomicLong 数值的属性，它是被 volatile 修饰的，所以它需要保证自身可见性。
 *
 * 这样一来，每一次它的数值有变化的时候，它都需要进行 flush 和 refresh。比如说，如果开始时，ctr 的数值为 0 的话，那么如图所示，一旦
 * core 1 把它改成 1 的话，它首先会在左侧把这个 1 的最新结果给 flush 到下方的共享内存。然后，再到右侧去往上 refresh 到核心 2 的
 * 本地内存。这样一来，对于核心 2 而言，它才能感知到这次变化。
 * 由于竞争很激烈，这样的 flush 和 refresh 操作耗费了很多资源，而且 CAS 也会经常失败。
 *
 * 在16个线程下使用AtomicLong
 * @author qian
 * @version 1.0
 * @date 2022/3/2 15:00
 */
public class AtomicLongDemo {

    public static void main(String[] args) throws InterruptedException {
        AtomicLong counter = new AtomicLong(0);
        ExecutorService executorService = new ThreadPoolExecutor(16, 16,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>());

        for (int i = 0; i < 100; i++) {
            executorService.submit(new Task(counter));
        }

        Thread.sleep(2000);
        System.out.println(counter.get());
    }


    static class Task implements Runnable{

        private final AtomicLong counter;

        public Task(AtomicLong counter){
           this.counter = counter;
        }

        @Override
        public void run() {
            counter.incrementAndGet();
        }
    }
}
